package com.traffic.api.jedis;

import java.util.Set;

import com.traffic.api.config.ApiProperties;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * 
 * 类名称: JedisClient 类描述: redis 单例模式 备注: 饿汉
 */
public class JedisClient {

	private JedisPool jedisPool;

	private final ThreadLocal<Jedis> threadLocalJedis = new ThreadLocal<Jedis>();

	private static final NamingRule keynamingRule = NamingRule.defaultKeyNamingPolicy;

	private static JedisClient jedisClient = new JedisClient();

	private JedisClient() {
		JedisPoolConfig  jedisPoolConfig= new JedisPoolConfig();
		
		jedisPool = new JedisPool(jedisPoolConfig, ApiProperties.REDIS_HOST,
				ApiProperties.REDIS_PORT, 1800, ApiProperties.REDIS_PASSWORD,
				14);
	}

	// 开放一个公有方法，判断是否已经存在实例，有返回，没有新建一个在返回
	public static JedisClient getInstance() {
		return jedisClient;
	}

	@SuppressWarnings("unchecked")
	public <T> T get(Object key) {
		Jedis jedis = getJedis();
		try {
			return (T) valueFromBytes(jedis.get(keyToBytes(key)));
		} finally {
			close(jedis);
		}
	}

	public String set(Object key, Object value) {
		Jedis jedis = getJedis();
		try {
			return jedis.set(keyToBytes(key), valueToBytes(value));
		} finally {
			close(jedis);
		}
	}

	/**
	 * 存放 key value 对到 redis，并将 key 的生存时间设为 seconds (以秒为单位)。 如果 key 已经存在， SETEX
	 * 命令将覆写旧值。
	 */
	public String setex(Object key, int seconds, Object value) {
		Jedis jedis = getJedis();
		try {
			return jedis.setex(keyToBytes(key), seconds, valueToBytes(value));
		} finally {
			close(jedis);
		}
	}

	/**
	 * 存放 key value 对到 redis，并将 key 的生存时间设为 seconds (以秒为单位)。 如果 key 已经存在， SETEX
	 * 命令将覆写旧值。
	 */
	public Long setnx(String key, String value) {
		Jedis jedis = getJedis();
		try {
			return jedis.setnx(keyToBytes(key), valueToBytes(value));
		} finally {
			close(jedis);
		}
	}

	/**
	 * 检查给定 key 是否存在。
	 */
	public boolean exists(Object key) {
		Jedis jedis = getJedis();
		try {
			return jedis.exists(keyToBytes(key));
		} finally {
			close(jedis);
		}
	}
	
	/**
	 * 查找所有符合给定模式 pattern 的 key 。 KEYS * 匹配数据库中所有 key 。 KEYS h?llo 匹配 hello ，
	 * hallo 和 hxllo 等。 KEYS h*llo 匹配 hllo 和 heeeeello 等。 KEYS h[ae]llo 匹配 hello
	 * 和 hallo ，但不匹配 hillo 。 特殊符号用 \ 隔开
	 */
	public Set<String> keys(String pattern) {
		Jedis jedis = getJedis();
		try {
			return jedis.keys(pattern);
		} finally {
			close(jedis);
		}
	}

	private byte[] valueToBytes(Object object) {
		return JRESerialize.valueToBytes(object);
	}

	private Object valueFromBytes(byte[] bytes) {
		return JRESerialize.valueFromBytes(bytes);
	}

	private byte[] keyToBytes(Object key) {
		String keyStr = keynamingRule.getKeyName(key);
		return JRESerialize.keyToBytes(keyStr);
	}

	@SuppressWarnings("unused")
	private String keyFromBytes(byte[] bytes) {
		return JRESerialize.keyFromBytes(bytes);
	}

	public Jedis getJedis() {
		Jedis jedis = threadLocalJedis.get();
		return jedis != null ? jedis : jedisPool.getResource();
	}

	public void close(Jedis jedis) {
		if (threadLocalJedis.get() == null && jedis != null)
			jedisPool.returnResource(jedis);
	}

	public Jedis getThreadLocalJedis() {
		return threadLocalJedis.get();
	}

	public void setThreadLocalJedis(Jedis jedis) {
		threadLocalJedis.set(jedis);
	}

	public void removeThreadLocalJedis() {
		threadLocalJedis.remove();
	}
}
